#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
#include<stdio.h>
#include<sys/time.h>
#define N 50
double A[4*N][4*N];
double C[4*N][4*N];
double B[4*N][4*N];
double* A1[4*N];
double* B1[4*N];
double* C1[4*N];
int s=0;

void gemm(double **A,double **B,double **C,int i,int j,int n)
{
    int a,b,c;
    for(a=0;a<n;a++)
    {
        for(b=0;b<n;b++)
        {
            for(c=0;c<4*n;c++)
             C[i*n+a][j*n+b]+=A[i*n+a][c]*B[c][j*n+b];
        }
    }
}
void increse_num(int *arg) {
	
	int flag = *arg;
	if(flag == 0)
	{
        s=s+1;
        
	}else if(flag == 1)
	{
		int t1=0+s;
        if(t1>3)
        {
            t1=t1-4;
        }
		gemm(A1,B1,C1,0,t1,N);	
	}else if(flag == 2)
	{
		int t2=1+s;
        if(t2>3)
        {
            t2=t2-4;
        }
		gemm(A1,B1,C1,1,t2,N);	
	}else if(flag == 3)
	{
		int t3=2+s;
        if(t3>3)
        {
            t3=t3-4;
        }
		gemm(A1,B1,C1,2,t3,N);	
	}else
	{
		int t4=3+s;
        if(t4>3)
        {
            t4=t4-4;
        }
		gemm(A1,B1,C1,3,t4,N);	
	}
}


int main(void)
{
    int n=N;
    double speedup;
    double time2;
    double time1;
	struct timeval start;
	struct timeval end;
    int i,j,k;
    int ret;
    int flag;
    pthread_t thrd1, thrd2, thrd3, thrd4, thrd5;
    for(i=0;i<4*n;i++)
    {
       for(j=0;j<4*n;j++)
        {
            A[i][j]=B[i][j]=rand()%10+1;
            C[i][j]=0;
         }
    }
    for(i=0;i<4*n;i++)
    {
        A1[i]=A[i];
        B1[i]=B[i];
        C1[i]=C[i];
    }
    
    
	
    
	
	gettimeofday(&start,NULL);
    for(s=0;s<4;)
    {
     flag = 1;
    ret = pthread_create(&thrd1, NULL, (void *)increse_num, &flag);
	
    
    
	sleep(1);   
	
	flag = 2;
    ret = pthread_create(&thrd2, NULL, (void *)increse_num, &flag);
       
	
    sleep(1);

	flag = 3;
    ret = pthread_create(&thrd3, NULL, (void *)increse_num, &flag);
    

    sleep(1);   
	
	flag = 4;
    ret = pthread_create(&thrd4, NULL, (void *)increse_num, &flag);
	pthread_join(thrd3, NULL);
    pthread_join(thrd2, NULL);
    pthread_join(thrd1, NULL);
    pthread_join(thrd4, NULL);
    
    
    


    flag=0;
	increse_num(&flag);
       
    }
    gettimeofday(&end,NULL);
    time1=1000000*(end.tv_sec-start.tv_sec)+(end.tv_usec-start.tv_usec);
    time1/=1000000;
    //for(i=0;i<4*n;i++)
    {
       //for(j=0;j<4*n;j++)
        {
           // printf("%f\t",C[i][j]);
         }
        // printf("\n");

    }
    for(i=0;i<4*n;i++)
    {
       for(j=0;j<4*n;j++)
        {
            A[i][j]=B[i][j]=rand()%10+1;
            C[i][j]=0;
         }
    }
    gettimeofday(&start,NULL);
    for(i = 0 ; i<4*n ; i++){
			for(j = 0 ; j < 4*n ; j++){
				
                for(k=0;k<4*n;k++)
				{
					C[i][j] += A[i][k]*B[k][j];
					
				}
				
			}
		} 	
		gettimeofday(&end,NULL);
        time2=1000000*(end.tv_sec-start.tv_sec)+(end.tv_usec-start.tv_usec);
        time2/=1000000;
        speedup=time2/(time1-12);
        for(i=0;i<4*n;i++)
    {
       //for(j=0;j<4*n;j++)
        {
           // printf("%f\t",C[i][j]);
         }
        // printf("\n");

    }
    printf("规模为%d,多线程分块矩阵乘法所需时间：%f ",4*n,time1);
    printf("常规矩阵乘法所需时间：%f  加速比为%f",time2,speedup);
    return 0;
}